#include "ema.h"

#include <iostream>
#include <stdexcept>

Ema::Ema(int period, bool isInitialized) {
    if (period <= 0) {
        throw std::invalid_argument("周期必须为正数");
    }
    alpha = 2.0 / (period + 1.0);
}

// 重置计算器状态
void Ema::reset() {
    isInitialized = false;
    currentEMA = 0.0;
}

// 计算单个新数据点的EMA
double Ema::calculate(double price) {
    if (!isInitialized) {
        // 第一个数据点，EMA等于自身
        currentEMA = price;
        isInitialized = true;
    } else {
        // EMA计算公式：EMA = (价格 * alpha) + (前一个EMA * (1 - alpha))
        currentEMA = (price * alpha) + (currentEMA * (1 - alpha));
    }
    return currentEMA;
}

// 批量计算一组数据的EMA
std::vector<double> Ema::calculateBatch(const std::vector<double>& prices) {
    std::vector<double> emas;
    emas.reserve(prices.size());

    reset();
    for (double price : prices) {
        emas.push_back(calculate(price));
    }

    return emas;
}

// 获取当前EMA值
const double Ema::getCurrentEMA()  {
    if (!isInitialized) {
        throw std::runtime_error("EMA尚未初始化，请先输入数据");
    }
    return currentEMA;
}

// 获取周期
const int Ema::getPeriod() {
    return period;
}

// 获取平滑系数
const double Ema::getAlpha() {
    return alpha;
}

int testEmaMain() {
    try {
        // 创建一个周期为12的EMA计算器
        Ema ema12(12);

        // 示例数据 - 可以替换为实际价格数据
        std::vector<double> prices = {
            22.27, 22.19, 22.08, 22.17, 22.18, 22.13,
            22.23, 22.43, 22.24, 22.29, 22.15, 22.39,
            22.38, 22.61, 23.36, 24.05, 23.75, 23.83
        };

        // 计算批量EMA
        std::vector<double> emas = ema12.calculateBatch(prices);

        // 输出结果
        std::cout << "周期为" << ema12.getPeriod() << "的EMA计算结果：\n";
        std::cout << "价格\tEMA\n";
        std::cout << "-----------------\n";

        for (size_t i = 0; i < prices.size(); ++i) {
            printf("%.2f\t%.4f\n", prices[i], emas[i]);
        }

        // 演示实时计算
        double newPrice = 23.95;
        double newEma = ema12.calculate(newPrice);
        std::cout << "\n添加新价格 " << newPrice << " 后的EMA: " << newEma << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
